﻿using System;
using System.Collections.Generic;

using System.Text;
using Silk.NET.Core.Native;
using TTEngine.Resource;
using TTEngine.TTMath;

namespace TTEngine.Graphics
{
    public struct FrameInfo
    {
        public uint DrawCount;
        public uint DrawElemCount;
        public DateTime FrameBegin;
        public DateTime FrameEnd;
    }
    //收集一个基本的渲染信息
    public class RenderInfo
    {
        public uint DrawCount;
        public uint DrawElemCount;
        public DateTime FrameBegin;
        public int HistoryMaxCount
        {
            get;
            private set;
        }
      
        public RenderInfo( int historyCount = 120)
        {

            HistoryMaxCount = historyCount;
        }
        public Queue<FrameInfo> History = new Queue<FrameInfo>();
        public void RecordFrame_Begin()
        {
            DrawCount = 0;
            DrawElemCount = 0;
            FrameBegin = DateTime.Now;
        }
        public void RecordFrame_End()
        {
            History.Enqueue(new FrameInfo()
            {
                DrawCount = this.DrawCount,
                DrawElemCount = this.DrawElemCount,
                FrameBegin = this.FrameBegin,
                FrameEnd = DateTime.Now
            });
            if (History.Count > HistoryMaxCount)
                History.Dequeue();
        }
        public float GetLast(int count, List<FrameInfo> result)
        {

            int skip = 0;
            int realcount = count;
            if (count > History.Count)
            {
                skip = count - History.Count;
                realcount = History.Count;
            }
            float maxtime = 0;
            foreach (var h in History)
            {
                if (skip > 0)
                {
                    skip--;
                }
                else
                {
                    var time = (float)(h.FrameEnd - h.FrameBegin).TotalMilliseconds;
                    if (time > maxtime)
                        maxtime = time;
                    result.Add(h);
                }
            }
            return maxtime;

        }

        List<FrameInfo> result = new List<FrameInfo>();
        public void DrawStats(CommonResource _resource,PackedTextureBatcher render, fAABB rect, float scale, bool withBorder = false, string[] addlog=null)
        {
            render.EndDraw();
            render.ZTest = false;
            render.ZWrite = false;

            if (withBorder)
            {
                render.DrawSpriteScale9(_resource.PackedTextureGroup, _resource.BlockBorderRound,
              Border.Create(3), scale,
             rect, 0, Color.White);
            }
            result.Clear();
            var maxtime = GetLast(90, result);
            if (result.Count > 2)
            {
                var delta = (result[result.Count - 1].FrameBegin - result[0].FrameBegin).TotalSeconds;
                var fps = (result.Count - 1) / delta;

                if (withBorder)
                {
                    for (var x = 0; x < result.Count; x++)
                    {
                        var index = result.Count - 1 - x;

                        float linex2 = rect.x2 - (4 + x * 2) * scale;
                        float liney2 = rect.y2 - 4 * scale;
                        float h = (float)(result[index].FrameEnd - result[index].FrameBegin).TotalMilliseconds / maxtime;
                        if (h > 1.0f) h = 1.0f;
                        float liney1 = liney2 - 32 * h * scale;
                        render.DrawSprite(_resource.PackedTextureGroup, _resource.BlockWhite,
                      new fAABB(linex2 - (1) * scale + 1 * scale, liney1 + 1 * scale, linex2 + 1 * scale, liney2 + 1 * scale), 0,
                      new Color(0f, 0f, 0f, 0.5f));

                        render.DrawSprite(_resource.PackedTextureGroup, _resource.BlockWhite,
                            new fAABB(linex2 - (1) * scale, liney1, linex2, liney2), 0,
                            new Color(0.1f, 0.4f, 0.8f, 0.8f));

                    }
                }
                render.DrawFont(_resource.AscII12, "Fps:" + fps.ToString("f02"), rect.x1 + 5 * scale, rect.y1 + 5 * scale, 0, new Color(0, 0, 0, 0.5f), scale, 1);
                render.DrawFont(_resource.AscII12, "MaxDrawTime(MS):" + maxtime.ToString("f02"), rect.x1 + 5 * scale, rect.y1 + 17 * scale, 0, new Color(0, 0, 0, 0.5f), scale, 1);
                render.DrawFont(_resource.AscII12, "DrawCall:" + this.DrawCount, rect.x1 + 5 * scale, rect.y1 + 29 * scale, 0, new Color(0, 0, 0, 0.5f), scale, 1);
                render.DrawFont(_resource.AscII12, "DrawElem:" + this.DrawElemCount, rect.x1 + 5 * scale, rect.y1 + 41 * scale, 0, new Color(0, 0, 0, 0.5f), scale, 1);
                render.DrawFont(_resource.AscII12, "Fps:" + fps.ToString("f02"), rect.x1 + 4 * scale, rect.y1 + 4 * scale, 0, Color.White, scale, 1);
                render.DrawFont(_resource.AscII12, "MaxDrawTime(MS):" + maxtime.ToString("f02"), rect.x1 + 4 * scale, rect.y1 + 16 * scale, 0, Color.White, scale, 1);
                render.DrawFont(_resource.AscII12, "DrawCall:" + this.DrawCount, rect.x1 + 4 * scale, rect.y1 + 28 * scale, 0, Color.White, scale, 1);
                render.DrawFont(_resource.AscII12, "DrawElem:" + this.DrawElemCount, rect.x1 + 4 * scale, rect.y1 + 40 * scale, 0, Color.White, scale, 1);
                if(addlog!=null)
                {
                    for(var i=0;i<addlog.Length;i++)
                    {
                        render.DrawFont(_resource.AscII12, addlog[i], rect.x1 + 5 * scale, rect.y1 + 53 * scale + i * 12 * scale, 0, new Color(0, 0, 0, 0.5f), scale, 1);
                        render.DrawFont(_resource.AscII12, addlog[i], rect.x1 + 4 * scale, rect.y1 + 52 * scale + i*12* scale, 0, Color.White, scale, 1);
                    }
                }
            }
            render.EndDraw();
        }
    }
}
